#ifndef C_SERIAL_COMMAND_CONTROLLOR_H_
#define C_SERIAL_COMMAND_CONTROLLOR_H_

#include "ISerialCommand.h"
#include <mutex>
#include <thread>
#include <condition_variable>

#include <list>

namespace zl
{
namespace zlmodules
{

class CSerialCommandControllor : public ISerialCommand
{
public:
    CSerialCommandControllor(ISerialCommandEventNotice* obs);
    ~CSerialCommandControllor();

    /// \brief 连接打开串口
    int32_t Connect(const std::string& port, int32_t baud) override;

    /// \brief 关闭串口连接
    void Disconnect() override;

    /// \brief 关闭开关电源 n秒后重启
    int32_t ResetSwitchPowerCommand(zl::zlmodules::SwitchType switch_type, int32_t seconds) override;

protected:

    /// \brief 关闭开关电源 n秒后重启
    int32_t cmd_reset_switch_power_command(zl::zlmodules::SwitchType switch_type, int32_t seconds);

    /// \brief 解析指令回复
    int32_t analyze_receive_cmd_buffer();

    /// \brief 解析消息回复
    int32_t analyze_receive_msg_buffer();

    bool cv_wait(int32_t timeout = 1000);
    size_t sync_write_cmd(unsigned char* buff, size_t len, int32_t timeout = 300);

    /// \brief 解析接收的内存数据
    void process_package(const unsigned char* pkg, size_t len);

    /// \brief 开启读取接收线程
    void start_read_work_thread();

    // 获取当前命令的指令索引号
    unsigned char get_cmd_index(unsigned char cmd);

    // 将指令索引号 加入保存队列
    int32_t add_cmd_index(unsigned char cmd, unsigned char index);

    // 判断指令索引号 是否在保存队列中
    int32_t is_index_valid(unsigned char cmd, unsigned char index);

    // 从保存队列中 将指令索引号删除
    int32_t remove_cmd_index(unsigned char cmd, unsigned char index);
private:
    struct IOImpl;
    IOImpl *io_;

    std::mutex mutex_;
    std::mutex mutex_cv_;
    std::condition_variable cv_;
    bool flag_cv_;
    struct IOReply;
    IOReply* io_reply_;

    bool io_read_flag_;
    std::thread* io_read_thread_;                               // 读取线程

    ISerialCommandEventNotice* obs_;                            // 观察者模式观察对象

    std::list<unsigned char> switch_power_reset_cmd_list;       // 发出的开关电源重启命令 所有的命令序号保存到队列
};

} // namespace zlmodules
} // namespace zl

#endif // C_SERIAL_COMMAND_CONTROLLOR_H_
